package com.mic.yzzn.plc.core.control;

import com.mic.yzzn.plc.common.control.RMI.PLCMaster;
import com.mic.yzzn.plc.common.control.datastructure.PLCCollectorControlCmd;
import com.mic.yzzn.plc.common.control.datastructure.PLCCollectorQueueStatus;
import com.mic.yzzn.plc.common.control.datastructure.PLCCollectorStatus;
import com.mic.yzzn.plc.core.control.datastructure.PLCContext;
import com.mic.yzzn.plc.core.plcevents.PLCCycleEvent;
import com.mic.yzzn.plc.core.plcevents.PLCNewCollectorEvent;
import com.mic.yzzn.plc.core.plcevents.PLCRealtimeEvent;
import com.mic.yzzn.plc.core.plcevents.listener.PLCEventListener;
import com.mic.yzzn.plc.core.plcevents.listener.PLCNewCollectorEventListener;
import org.apache.log4j.Logger;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Master的实现类,负责管理Context和控制各个采集器
 */
public class PLCCollectorMasterImpl extends UnicastRemoteObject implements PLCEventListener, PLCNewCollectorEventListener, PLCMaster, Serializable
{
	/** PLC上下文 */
	private PLCContext context;
	/** 采集器状态Map */
	private ConcurrentHashMap<String, PLCCollectorStatus> collectorStatus = new ConcurrentHashMap<String, PLCCollectorStatus>();
	/** Logger */
	private static Logger logger = Logger.getLogger(PLCCollectorMasterImpl.class);

    public PLCCollectorMasterImpl() throws RemoteException
    {
    	super();
    }

	public PLCContext getContext()
	{
		return context;
	}

	/**
	 * 实时任务事件监听方法
	 */
	@Override
	public void notifyRealtimeEvent(PLCRealtimeEvent realtimeEvent)
	{
		PLCCollectorQueueStatus queueStatuss = realtimeEvent.getStatus();
		PLCCollectorStatus cs = collectorStatus.get(queueStatuss.getCollectorID());
		PLCCollectorImpl collector = context.getCollectorWithID(queueStatuss.getCollectorID());

		// 如果为空则创建新的
		if (cs == null)
		{
			cs = new PLCCollectorStatus();
			cs.setCollectorID(queueStatuss.getCollectorID());
		}

		cs.setCollectorStartTime(collector.getStartTime());

		if (queueStatuss.getInstructionPriority() == 0)
		{
			cs.setRealTimeWriteQueueState(queueStatuss);
		}
		else if (queueStatuss.getInstructionPriority() == 1)
		{
			cs.setRealTimeReadQueueState(queueStatuss);
		}

		setState(collector, cs);
        collectorStatus.put(cs.getCollectorID(), cs);

		System.out.println(cs);
		System.out.println();
	}

	/**
	 * 周期任务事件监听方法
	 */
	@Override
	public void notifyCycleEvent(PLCCycleEvent cycleEvent)
	{
		PLCCollectorQueueStatus queueStatuss = cycleEvent.getStatus();
		PLCCollectorStatus cs = collectorStatus.get(queueStatuss.getCollectorID());
		PLCCollectorImpl collector = context.getCollectorWithID(queueStatuss.getCollectorID());

		// 如果为空则创建新的
		if (cs == null)
		{
			cs = new PLCCollectorStatus();
			cs.setCollectorID(queueStatuss.getCollectorID());
			cs.getRealTimeReadQueueState().setCollectorID(queueStatuss.getCollectorID());
			cs.getRealTimeReadQueueState().setInstructionPriority(1);
			cs.getRealTimeWriteQueueState().setCollectorID(queueStatuss.getCollectorID());
		}

		cs.setCollectorStartTime(collector.getStartTime());
		cs.setCycleQueueState(queueStatuss);

		setState(collector, cs);
        collectorStatus.put(cs.getCollectorID(), cs);

		System.out.println(cs);
		System.out.println();
	}

	private void setState(PLCCollectorImpl collector, PLCCollectorStatus cs) {
		if (collector.isStop())
		{
			cs.setState(PLCCollectorStatus.PLCCollectorStateStop);
		}
		else if (collector.isAsleep())
		{
			cs.setState(PLCCollectorStatus.PLCCollectorStateSleep);
		}
		else
		{
			cs.setState(PLCCollectorStatus.PLCCollectorStateActive);
		}
	}
	
	/**
	 * 新采集器事件监听方法
	 */
	@Override
	public void notifyNewCollectorAdded(PLCNewCollectorEvent event)
	{
		event.getCollector().addCycleEventListener(this);
		event.getCollector().addRealtimeEventListener(this);
	}
	
	public void setContext(PLCContext context)
	{
		this.context = context;
		context.addNewCollectorEventListener(this);
	}

	// RMI Interface

	/**
	 * 获取指定采集器的状态
	 * @param collectorID 采集器的ID
	 * @return 采集器的状态
	 * @throws RemoteException
     */
	@Override
	public PLCCollectorStatus getCollectorStateFromID(String collectorID) throws RemoteException
	{
        System.out.println("################## " + collectorID + " #################");
		return collectorStatus.get(collectorID);
	}

	/**
	 * 控制指定的采集器
	 * @param cmd 采集器控制指令
	 * @return 控制的结果
	 * @throws RemoteException
     */
	@Override
	public int controlCollector(PLCCollectorControlCmd cmd) throws RemoteException
	{
		return context.controlCollector(cmd);
	}

	/**
	 * 批量获取采集器的状态
	 * @param collectorIDs 采集器状态数组
	 * @return 对应采集器状态的Map
	 * @throws RemoteException
     */
	@Override
	public Map<String, PLCCollectorStatus> getCollectorStatesFromIDs(List<String> collectorIDs) throws RemoteException
	{
		HashMap<String, PLCCollectorStatus> resultMap = new HashMap<>();

		for (String key : collectorIDs)
		{
			PLCCollectorStatus status = collectorStatus.get(key);
			if (status != null)
			{
				resultMap.put(key, status);
			}
		}

		return resultMap;
	}
}
